 
package com.zdkj.subway.rca.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zdkj.common.security.service.PigxUser;
import com.zdkj.common.security.util.SecurityUtils;
import com.zdkj.subway.rca.entity.SwCkDiffAfterClear;
import com.zdkj.subway.rca.entity.SwCkDiffAfterClearReport;
import com.zdkj.subway.rca.mapper.SwCkDiffAfterClearMapper;
import com.zdkj.subway.rca.service.SwCkClearRulesService;
import com.zdkj.subway.rca.service.SwCkDiffAfterClearReportService;
import com.zdkj.subway.rca.service.SwCkDiffAfterClearService;
import com.zdkj.subway.rca.util.LocalDateConverter;
import com.zdkj.subway.rca.util.LocalDateTimeConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 清分后数据差异
 *
 * @author stw
 * @date 2021-01-03 21:22:15
 */
@Service
public class SwCkDiffAfterClearServiceImpl extends ServiceImpl<SwCkDiffAfterClearMapper, SwCkDiffAfterClear> implements SwCkDiffAfterClearService {
    private static final Logger LOGGER = LoggerFactory.getLogger(SwCkDiffAfterClearServiceImpl.class);
    @Autowired
    private SwCkClearRulesService swCkClearRulesService;
    @Autowired
    private SwCkDiffAfterClearReportService swCkDiffAfterClearReportService;

    @Override
    public List<Map<String,String>> getTicketTypeMap(){
        return this.baseMapper.getTicketTypeMap();
    }

    @Override
    public List<Map<String,String>> getAdjustReasonMap(){
        return this.baseMapper.getAdjustReasonMap();
    }

    @Override
    public Boolean confirm(List<Long> ids) {
        Boolean flag = false;
        PigxUser user = SecurityUtils.getUser();
        List<SwCkDiffAfterClear> list = new ArrayList<>();
        List<SwCkDiffAfterClearReport> listReport = new ArrayList<>();
        for(Long id : ids) {
            SwCkDiffAfterClear swCkDiffAfterClear = this.getById(id);
            if("1".equals(swCkDiffAfterClear.getConfirmStatus())) {
                continue;
            }
            SwCkDiffAfterClearReport swCkDiffAfterClearReport = new SwCkDiffAfterClearReport();
            swCkDiffAfterClearReport.setOperators(swCkDiffAfterClear.getOperators());
            swCkDiffAfterClearReport.setLineCode(swCkDiffAfterClear.getLineCode());
            swCkDiffAfterClearReport.setStatisticsMonth(swCkDiffAfterClear.getEndTime().plusMonths(1).format(DateTimeFormatter.ofPattern("yyyy-MM")) );
            swCkDiffAfterClearReport.setLastClearMoney(swCkDiffAfterClear.getLastClearMoney());
            swCkDiffAfterClearReport.setCurrClearMoney(swCkDiffAfterClear.getCurrClearMoney());
            swCkDiffAfterClearReport.setDiffMoney(swCkDiffAfterClear.getDiffMoney());
            swCkDiffAfterClearReport.setTicketType(swCkDiffAfterClear.getTicketType());
            swCkDiffAfterClearReport.setDeptId(user.getDeptId());
            swCkDiffAfterClearReport.setCreatorId(user.getId());
            swCkDiffAfterClearReport.setCreatorName(user.getNikeName());
            listReport.add(swCkDiffAfterClearReport);

            //改为已确认
            swCkDiffAfterClear.setConfirmStatus("1");
            list.add(swCkDiffAfterClear);
        }

        if (!listReport.isEmpty()) {
            flag = swCkDiffAfterClearReportService.saveBatch(listReport);
        }
        if(flag) {
            this.updateBatchById(list);
        }
        return flag;
    }

    @Override
    public void export(String operators,String lineCode,String startDate,String endDate, HttpServletResponse response) {

        List<Map<String,String>> lineMap = this.baseMapper.selectLineMap();
        List<Map<String,String>> serviceMap = swCkClearRulesService.getServiceMap();
        List<Map<String,String>> ticketTypeMap = this.baseMapper.getTicketTypeMap();
        List<Map<String,String>> adjustReasonMap = this.baseMapper.getAdjustReasonMap();

        List<SwCkDiffAfterClear> records = getSelect(operators, lineCode, startDate, endDate);
        if(CollectionUtil.isNotEmpty(records)){
            for (SwCkDiffAfterClear record : records) {
                record.setAdjustReason(getAdjustReasonName(adjustReasonMap,record.getAdjustReason()));
            }
        }
        InputStream excelTemplateIs = null;
        try {response.reset(); // 非常重要
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            final String fileName = URLEncoder.encode("清分后数据差异", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + System.currentTimeMillis() + ".xlsx");

            // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
            // {} 代表普通变量 {.} 代表是list的变量

            excelTemplateIs = this.getClass().getResourceAsStream("/static/excel/template/export/SwCkDiffAfterClearExcelTemplate.xlsx");

            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).registerConverter(new LocalDateTimeConverter()).registerConverter(new LocalDateConverter()).withTemplate(excelTemplateIs).build();
            WriteSheet writeSheet = EasyExcel.writerSheet("清分后数据差异").build();
            // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行，然后下面的数据往后移动。默认 是false，会直接使用下一行，如果没有则创建。
            // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了，所以慎用
            // 简单的说 如果你的模板有list,且list不是最后一行，下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
            // 如果数据量大 list不是最后一行 参照另一个
            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.FALSE).build();
            excelWriter.fill(records, fillConfig, writeSheet);
            Map<String, Object> map = new HashMap<>();
            map.put("beginTime", startDate);
            map.put("endTime", endDate);
            excelWriter.fill(map, writeSheet);
            excelWriter.finish();

        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error("导出清分后数据差异异常");
        } finally {
            if(excelTemplateIs != null){
                try {
                    excelTemplateIs.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
    }

    @Override
    public List<SwCkDiffAfterClear> getSelect(String operators, String lineCode, String startDate, String endDate) {
        List<SwCkDiffAfterClear> list = this.baseMapper.getSelect(operators, lineCode, startDate, endDate);
        List<SwCkDiffAfterClear> listNew = new ArrayList<>();

        String operatorsName = null;
        for(SwCkDiffAfterClear obj : list){
            if(!obj.getOperatorsName().equals(operatorsName) && operatorsName != null){
                SwCkDiffAfterClear sum = getSum(operatorsName, list);
                listNew.add(sum);
            }
            operatorsName = obj.getOperatorsName();
            listNew.add(obj);
        }
        if(list.size() > 0) { //最后一个运营商
            SwCkDiffAfterClear sum = getSum(operatorsName, list);
            listNew.add(sum);
        }

        SwCkDiffAfterClear sumAll  = getSum("合计",list);
        sumAll.setLineCode("--");
        sumAll.setLineName("--");
        listNew.add(sumAll);
        return listNew;
    }

    private SwCkDiffAfterClear getSum(String operatorsName,List<SwCkDiffAfterClear> list){
        SwCkDiffAfterClear sumSwCkDiffAfterClear = new SwCkDiffAfterClear();
        sumSwCkDiffAfterClear.setOperatorsName(operatorsName);
        sumSwCkDiffAfterClear.setLineName("小计");
        sumSwCkDiffAfterClear.setLineCode("小计");
        if("合计".equals(operatorsName)){
            sumSwCkDiffAfterClear.setOperators("合计");
            sumSwCkDiffAfterClear.setOperatorsName("合计");
        }


        for (SwCkDiffAfterClear afterClear : list) {
            if(operatorsName.equals("合计") || operatorsName.equals(afterClear.getOperatorsName())) {
                sumSwCkDiffAfterClear.setFirstReceivableOnewayReceivedClean(getData(sumSwCkDiffAfterClear.getFirstReceivableOnewayReceivedClean()).add(afterClear.getFirstReceivableOnewayReceivedClean().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setFirstReturnOnewayReceivedClean(getData(sumSwCkDiffAfterClear.getFirstReturnOnewayReceivedClean()).add(afterClear.getFirstReturnOnewayReceivedClean().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setFirstSumOnewayReceivedClean(getData(sumSwCkDiffAfterClear.getFirstSumOnewayReceivedClean()).add(afterClear.getFirstSumOnewayReceivedClean().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setFirstCountingTicket(getData(sumSwCkDiffAfterClear.getFirstCountingTicket()).add(afterClear.getFirstCountingTicket().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setFirstDailyTicket(getData(sumSwCkDiffAfterClear.getFirstDailyTicket()).add(afterClear.getFirstDailyTicket().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setFirstCommemorativeTicket(getData(sumSwCkDiffAfterClear.getFirstCommemorativeTicket()).add(afterClear.getFirstCommemorativeTicket().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setFirstCat(getData(sumSwCkDiffAfterClear.getFirstCat()).add(afterClear.getFirstCat().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setFirstTrafficCard(getData(sumSwCkDiffAfterClear.getFirstTrafficCard()).add(afterClear.getFirstTrafficCard().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setFirstQrCodeTicket(getData(sumSwCkDiffAfterClear.getFirstQrCodeTicket()).add(afterClear.getFirstQrCodeTicket().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setFirstFaceTicketCcb(getData(sumSwCkDiffAfterClear.getFirstFaceTicketCcb()).add(afterClear.getFirstFaceTicketCcb().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setFirstIncomeSubtotal(getData(sumSwCkDiffAfterClear.getFirstIncomeSubtotal()).add(afterClear.getFirstIncomeSubtotal().setScale(2,BigDecimal.ROUND_HALF_UP)));

                sumSwCkDiffAfterClear.setCurrentReceivableOnewayReceivedClean(getData(sumSwCkDiffAfterClear.getCurrentReceivableOnewayReceivedClean()).add(afterClear.getCurrentReceivableOnewayReceivedClean().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setCurrentReturnOnewayReceivedClean(getData(sumSwCkDiffAfterClear.getCurrentReturnOnewayReceivedClean()).add(afterClear.getCurrentReturnOnewayReceivedClean().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setCurrentSumOnewayReceivedClean(getData(sumSwCkDiffAfterClear.getCurrentSumOnewayReceivedClean()).add(afterClear.getCurrentSumOnewayReceivedClean().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setCurrentCountingTicket(getData(sumSwCkDiffAfterClear.getCurrentCountingTicket()).add(afterClear.getCurrentCountingTicket().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setCurrentDailyTicket(getData(sumSwCkDiffAfterClear.getCurrentDailyTicket()).add(afterClear.getCurrentDailyTicket().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setCurrentCommemorativeTicket(getData(sumSwCkDiffAfterClear.getCurrentCommemorativeTicket()).add(afterClear.getCurrentCommemorativeTicket().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setCurrentCat(getData(sumSwCkDiffAfterClear.getCurrentCat()).add(afterClear.getCurrentCat().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setCurrentTrafficCard(getData(sumSwCkDiffAfterClear.getCurrentTrafficCard()).add(afterClear.getCurrentTrafficCard().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setCurrentQrCodeTicket(getData(sumSwCkDiffAfterClear.getCurrentQrCodeTicket()).add(afterClear.getCurrentQrCodeTicket().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setCurrentFaceTicketCcb(getData(sumSwCkDiffAfterClear.getCurrentFaceTicketCcb()).add(afterClear.getCurrentFaceTicketCcb().setScale(2,BigDecimal.ROUND_HALF_UP)));
                sumSwCkDiffAfterClear.setCurrentIncomeSubtotal(getData(sumSwCkDiffAfterClear.getCurrentIncomeSubtotal()).add(afterClear.getCurrentIncomeSubtotal().setScale(2,BigDecimal.ROUND_HALF_UP)));
            }
        }
        return sumSwCkDiffAfterClear;
    }

    private String getServiceName (List<Map<String,String>> serviceMap,String serviceId) {
        for (Map<String,String> map : serviceMap){
            if(serviceId.equals(map.get("operators"))){
                return map.get("operatorsName");
            }
        }
        return "";
    }

    private String getLineName (List<Map<String,String>>  lineMap, String lineCode) {
        for (Map<String,String> map : lineMap){
            if(lineCode.equals(map.get("CODE"))){
                return map.get("NAME");
            }
        }
        return "";
    }

    private String getAdjustReasonName (List<Map<String,String>> adjustReasonMap, String adjustReason) {
        if(StringUtils.isEmpty(adjustReason)){
            return "";
        }
        for (Map<String,String> map : adjustReasonMap){
            if(adjustReason.equals(map.get("adjustReason"))){
                return map.get("adjustReasonName");
            }
        }
        return "";
    }

    private String getTicketTypeName (List<Map<String,String>> ticketTypeMap, String ticketType) {
        for (Map<String,String> map : ticketTypeMap){
            if(ticketType.equals(map.get("ticketType"))){
                return map.get("ticketTypeName");
            }
        }
        return "";
    }

    private BigDecimal getData(BigDecimal money){
        try {
            if(money == null){
                return new  BigDecimal("0");
            }
            return money;

        } catch (Exception e) {
            return new  BigDecimal("0");
        }

    }
}
